import { RTColumn } from '../type/interfaces'
import {
  HorizontalRenderRange,
  RenderInfo,
  VisibleColumnDescriptor,
} from '../interfaces'
import { BaseTable } from './Table'
import { sum } from '../helpers/utils'



let lockColumnNeedSpecifiedWidthWarned = false
function warnLockColumnNeedSpecifiedWidth(column: RTColumn) {
  if (!lockColumnNeedSpecifiedWidthWarned) {
    lockColumnNeedSpecifiedWidthWarned = true
    console.warn('[react-table] lock=true 的列需要指定宽度', column)
  }
}

/** 检查列配置 & 设置默认宽度 & 剔除隐藏的列 */
function processColumns(columns: RTColumn[], defaultColumnWidth: number) {
  if (columns == null || !Array.isArray(columns)) {
    console.warn('[react-table] <BaseTable /> props.columns 需要传入一个数组', columns)
    columns = []
  }

  function dfs(columns: RTColumn[]): RTColumn[] {
    const result: RTColumn[] = []

    for (let column of columns) {
      if (column.width == null) {
        if (defaultColumnWidth != null) {
          column = { ...column, width: defaultColumnWidth }
        } else if (process.env.NODE_ENV !== 'production' && column.lock) {
          warnLockColumnNeedSpecifiedWidth(column)
        }
      }

        result.push(column)
    }
    return result
  }

  return dfs(columns)
}

function getLeftNestedLockCount(columns: RTColumn[]) {
  let nestedCount = 0

  for (const col of columns) {
    if (isLock(col)) {
      nestedCount += 1
    } else {
      break
    }
  }
  return nestedCount

  function isLock(col: RTColumn): boolean {
    return col.lock || false
  }
}

function getHorizontalRenderRange({
  flat,
}: {
  offsetX: number
  maxRenderWidth: number
  flat: RenderInfo['flat']
}): HorizontalRenderRange {
    return { leftIndex: 0, leftBlank: 0, rightIndex: flat.full.length, rightBlank: 0 }
}

// 计算渲染需要的数据
export function calculateRenderInfo(table: BaseTable): RenderInfo {
  const { offsetX, maxRenderWidth } = table.state

  const {
    columns: columnsProp,
    dataSource: dataSourceProp,
    defaultColumnWidth,
  } = table.props
   
  const tempColumns = processColumns(columnsProp, defaultColumnWidth)
  const columns = tempColumns
  const leftNestedLockCount = getLeftNestedLockCount(columns)
  const fullFlat = columns

  let flat: RenderInfo['flat']

  if (leftNestedLockCount === columns.length) {
    flat = { left: [], right: [], full: fullFlat, center: fullFlat }
  } else {
    const leftNested = columns.slice(0, leftNestedLockCount)
    const rightNestedLockCount = getLeftNestedLockCount(columns.slice().reverse())
    const centerNested = columns.slice(leftNestedLockCount, columns.length - rightNestedLockCount)
    const rightNested = columns.slice(columns.length - rightNestedLockCount)


    flat = {
      left: leftNested,
      full: fullFlat,
      right: rightNested,
      center: centerNested,
    }

  }

  const horizontalRenderRange = getHorizontalRenderRange({ maxRenderWidth, offsetX, flat })
  const verticalRenderRange = table.getVerticalRenderRange()

  const { leftBlank, leftIndex, rightBlank, rightIndex } = horizontalRenderRange
  const unfilteredVisibleColumnDescriptors: VisibleColumnDescriptor[] = [
    ...flat.left.map((col, i) => ({ type: 'normal', col, colIndex: i } as const)),
    leftBlank > 0 && { type: 'blank', blankSide: 'left', width: leftBlank },
    ...flat.center
      .slice(leftIndex, rightIndex)
      .map((col, i) => ({ type: 'normal', col, colIndex: flat.left.length + leftIndex + i } as const)),
    rightBlank > 0 && { type: 'blank', blankSide: 'right', width: rightBlank },
    ...flat.right.map(
      (col, i) => ({ type: 'normal', col, colIndex: flat.full.length - flat.right.length + i } as const),
    ),
  ]
  const visibleColumnDescriptors = unfilteredVisibleColumnDescriptors.filter(Boolean)

  const fullFlatCount = flat.full.length
  const leftFlatCount = flat.left.length
  const rightFlatCount = flat.right.length

  const stickyLeftMap = new Map<number, number>()
  let stickyLeft = 0
  for (let i = 0; i < leftFlatCount; i++) {
    stickyLeftMap.set(i, stickyLeft)
    stickyLeft += flat.full[i].width
  }

  const stickyRightMap = new Map<number, number>()
  let stickyRight = 0
  for (let i = 0; i < rightFlatCount; i++) {
    stickyRightMap.set(fullFlatCount - 1 - i, stickyRight)
    stickyRight += flat.full[fullFlatCount - 1 - i].width
  }

  const leftLockTotalWidth = sum(flat.left.map((col) => col.width))
  const rightLockTotalWidth = sum(flat.right.map((col) => col.width))

  return {
    horizontalRenderRange,
    verticalRenderRange,
    visible: visibleColumnDescriptors,
    flat,
    stickyLeftMap,
    stickyRightMap,
    leftLockTotalWidth,
    rightLockTotalWidth,
    hasLockColumn: flat.left.length > 0 || flat.right.length > 0,
  }
}
